/*
 Basado en:
 Tutorial # 0005 Arduino Academy - Sensor NTC
 http://www.arduteka.com/2011/12/tutorial-arduino-0005-sensor-de-temperatura-ntc/

 Conectamos una NTC a una entrada
 analógica para controlar cinco salidas
 en función de la temperatrura.
 
 Además utilizaremos un ponteciómetro para
 controlar la temperatura a partir de la cual
 se activarán las salidas
 
 Este proyecto es de dominio público.
 */
 
//Añadimos la librería math.h
#include <math.h>
 
//Pines para los LED
const int pinLed1 = 8;
const int pinLed2 = 9;
const int pinLed3 = 10;
const int pinLed4 = 11;
const int pinLed5 = 12;
 
//Pines para las entradas analógicas
const int analogPin1 = 0;
const int analogPin2 = 1;

//pin altavoz
const int speakerOut = 13;

 
//Escala de Avisos: salto en grados para encender un led más
int escala = 1;
 
//Datos para las ecuaciones
 
const float Vin = 5.0;     // [V]       Tensión alimentación del divisor
const float Rfija = 1000;  // [ohm]     Resistencia fija del divisor
const float R25 = 2800;    // [ohm]     Valor de NTC a 25ºC
const float Beta = 3950.0; // [K]      Parámetro Beta de NTC
const float T0 = 293.15;   // [K]       Temperatura de referencia en Kelvin
 
void setLedStatus(int led1, int led2, int led3, int led4, int led5) 
{
    digitalWrite(pinLed1, led1);
    digitalWrite(pinLed2, led2);
    digitalWrite(pinLed3, led3);
    digitalWrite(pinLed4, led4);
    digitalWrite(pinLed5, led5);
}

float getTemperature()
{
  //Primero la Vout del divisor de tensión donde está la NTCs
  float Vout=(Vin/1024)*(analogRead(analogPin1));
  //Ahora la resistencia de la NTC (en ohm)
  float Rntc=(Vout*Rfija)/(Vin-Vout);
  //Calculamos la temperatura en Kelvin resolviendo la ecuación
  float TempK = Beta/(log(Rntc/R25)+(Beta/T0));
  //Y ahora la pasamos a celsius
  float TempC = TempK - 273.15;
  return TempC;
}

double getBaseTempLevel()
{
    //Primero leemos el potenciómetro
  double tempMin = analogRead(analogPin2);
  //Mapeamos los valores de [0,1023] a valores de [-100,800]
  //Y lo dividimos entre 10 para darle un decimal
  tempMin = map(tempMin, 0, 1023, -100, 800) / 10;
  return tempMin;
}

bool sendAlarmSms()
{
  Serial.println("----------------- ¡¡ ALARMA !!-----------------------");
  Serial.println("----------------- ¡¡ ALARMA !!-----------------------");
  Serial.println("----------------- ¡¡ ALARMA !!-----------------------");
  Serial.println("----------------- ¡¡ ALARMA !!-----------------------");
  
  //zumbido
  /*
  * The calculation of the tones is made following the mathematical
  * operation:
  *
  *       timeHigh = 1/(2 * toneFrequency) = period / 2
  *
  * where the different tones are described as in the table:
  *
  * note         frequency       period  PW (timeHigh)   
  * c            261 Hz          3830    1915    
  * d            294 Hz          3400    1700    
  * e            329 Hz          3038    1519    
  * f            349 Hz          2864    1432    
  * g            392 Hz          2550    1275    
  * a            440 Hz          2272    1136    
  * b            493 Hz          2028    1014    
  * C            523 Hz          1912    956
  *
  */
  int repeatToneSequence =  5;
  for (int i = 0; i < repeatToneSequence; i++)
  {
    playTone(500, 25);
    playTone(1000, 25);
    playTone(1500, 50);
  }
}

void playTone(int hz, int cycles)
{
    int pulseWidth = 1000000 / (2 * hz);
    for (int toneCycles = 0; toneCycles < 60; toneCycles++)
    {
      analogWrite(speakerOut,500);
      delayMicroseconds(pulseWidth);
      analogWrite(speakerOut, 0);
      delayMicroseconds(pulseWidth);
    }
}


void setup() {
 
  //Comenzamos la comunicación puerto serie
  Serial.begin(9600);
 
  //Declaramos pines de salida
  pinMode(pinLed1, OUTPUT);
  pinMode(pinLed2, OUTPUT);
  pinMode(pinLed3, OUTPUT);
  pinMode(pinLed4, OUTPUT);
  pinMode(pinLed5, OUTPUT);
  
  pinMode(speakerOut, OUTPUT);
 
  //Y los pines de entrada
  pinMode(analogPin1, INPUT);
  pinMode(analogPin2, INPUT);
 
}
 
void loop()
{
  //Obtenemos el valor base a partir del cual se encienden los leds
  double tempMin = getBaseTempLevel();
 
  //Y lanzamos el ajuste establecido via serie
  Serial.println("-----------------------------------------------");
  Serial.print("AJUSTE DE TEMPERATURA MINIMA A ");
  Serial.print(tempMin);
  Serial.println(" GRADOS CELSIUS");
  Serial.println("-----------------------------------------------");
 
  //Y ahora calculamos la Temperatura
  float TempC = getTemperature();
 
  //Y lo mostramos por puerto serie
  Serial.println();
  Serial.print("LA TEMPERATURA DE LA NTC ES DE ");
  Serial.print(TempC);
  Serial.println(" GRADOS CELSIUS");
  Serial.println();
 
  //Ahora las comparaciones para las salidas
  if(TempC < tempMin)
    setLedStatus(HIGH, LOW, LOW, LOW, LOW);
  else if (((TempC <= (tempMin + escala)) & (TempC > tempMin)))
    setLedStatus(HIGH, HIGH, LOW, LOW, LOW);
  else if (((TempC<=(tempMin+(escala*2)))&(TempC>tempMin+escala)))
    setLedStatus(HIGH, HIGH, HIGH, LOW, LOW);
  else if ((TempC<=(tempMin+(escala*3)))&(TempC>tempMin+(escala*2)))
    setLedStatus(HIGH, HIGH, HIGH, HIGH, LOW);  
  else if (TempC > (tempMin + (escala*4)))
  {
    setLedStatus(HIGH, HIGH, HIGH, HIGH, HIGH);    
    sendAlarmSms();
  }
 
  //Un pequeño delay para no volver loco al puerto serie
  delay(500);
}
